#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess
from sets import Set
from copy import deepcopy

beta = 0.8
N = 875713
result_dict = {}
temp_dict = {}
param_dict = {}
node_set = Set()

#transmit input file using format like:
#source \t degree of source \t [target0, target1, ...]
def format(input_file, output_file):
    print 'format...'
    opf = open(output_file, 'w+')
    current_node = ''
    degree = 0
    target = []
    with open(input_file, 'r+') as f:
        for line in f:
            if '#' in line:
                continue
            from_node = line.strip().split('\t')[0]
            to_node = line.strip().split('\t')[1]
            if current_node != '' and current_node != from_node :
                opf.write(current_node + '\t' + str(degree) + '\t' + ', '.join(target) + '\n')
                degree = 0
                target = []
            current_node = from_node
            target.append(to_node)
            degree += 1
    opf.write(current_node + '\t' + str(degree) + '\t' + ', '.join(target) + '\n')       
    f.close()    
    opf.flush()
    opf.close()

def get_param(param_file):
    global param_dict
    
    print 'get param...'
    with open(param_file, 'r+') as f:
        for line in f:
            arr = line.strip().split('\t')
            param_dict[arr[0]] = float(arr[1])
    f.close()
    
#before calculating (in interation 0), all score is 1/N    
def iteration_0(input_file):
    global result_dict, node_set
    print 'iteration_0...'
    score = 1./N
    
    with open(input_file, 'r+') as f:
        for line in f:
            if '#' in line:
                continue
            from_node = line.strip().split('\t')[0]
            to_node = line.strip().split('\t')[1]
            node_set.add(from_node)
            node_set.add(to_node)
            
    f.close()  
    for node in node_set:
        result_dict[node] = score
    print 'result_dict{} size: %d' % len(result_dict)

# before calculating, score of all r(new) is (1-beta)/N
def init_score():
    global beta, N, node_set, temp_dict
    print 'initializing score...'
    
    init_score = (1.-beta)/N
    for node in node_set:
        temp_dict[node] = init_score
    print 'temp_dict{} size: %d' % len(temp_dict)

def calculate(format_file):
    global beta, N, result_dict, temp_dict
    init_score()
    
    print 'calculating...'
    counter = 0
    with open(format_file, 'r+') as f:
        for line in f:
            arr = line.strip().split('\t')
            source_score = beta * result_dict[arr[0]] / int(arr[1])
            for node in arr[2].split(','):
                node = node.strip()
                temp_dict[node] += source_score
            counter += 1
            if counter % 100000 == 0:
                print counter
    f.close()
    plus_param()
    
    result_dict = deepcopy(temp_dict)
    temp_dict.clear()
    
def plus_param():
    global temp_dict, param_dict
    print 'plus param...'
    for k, v in temp_dict.iteritems():
        param_score = param_dict[k]
        plus_score = shrink_param(v, param_score)
        temp_dict[k] = v + plus_score
        
def shrink_param(score, param_score):
    if '-' in str(score):
        s = str(score).split('-')[1]
        param_score *= (0.1**int(s)) * 10
        return param_score  
    else:
        s = str(score).split('.')[1]
        i = 0
        for num in s:
            if num is not '0':
                break
            i += 1
        param_score *= 0.1**i
        return param_score 
        
def output(output_file):
    global result_dict, node_set
    print 'output...'
    f = open(output_file, 'w+')
    for node in node_set:
        f.write('%s\t%10.10f\n' % (node, result_dict[node]))
            
    f.close()
    
def sort(source_file, target_file):
    sort = subprocess.Popen("sort -t '\t' -k2 -nr ", shell=True,
                    stdin=open(source_file, 'r'),
                    stdout=subprocess.PIPE,  # Not a pipe here,
                    )
    subprocess.Popen(" head -100 ", shell=True,
                    stdin=sort.stdout,
                    stdout=open(target_file, 'w'),  # Not a pipe here,
                    )
   
def main():
    input_file = '/home/ivy/git/BD_py/PageRank_py/project/resource/web-Google.txt'
    format_file = '/home/ivy/git/BD_py/PageRank_py/project/resource/format.txt'
    param_file = '/home/ivy/git/BD_py/PageRank_py/project/resource/param_cal.txt'
    output_file = '/home/ivy/git/BD_py/PageRank_py/project/resource/pagerank.txt'
    sort_file = '/home/ivy/git/BD_py/PageRank_py/project/resource/pagerank_sort.txt'
    
#     format(input_file, format_file)
    get_param(param_file)
    iteration_0(input_file)
    for i in range(1, 11):
        print 'iteration %d' % i
        calculate(format_file)
    output(output_file)
    sort(output_file, sort_file)
    
    
if __name__ == '__main__':
    main()